#include <vector>
#include <SDL/SDL.h>

#include "sdl.hpp"

namespace sdl
{
namespace gui
{

class Element
{
public:
    std::string id;
    sdl::Rect pos;
    static sdl::Surface* target;

    Element();
    virtual void render(){};
    virtual void event(const SDL_Event &event){};
protected:
    void drawFrame(bool inverted, Rect box);
};

class Container : public Element
{
protected:
    std::vector <Element*> children;
public:
    virtual void add(Element* child);
    virtual void render();
    virtual void event(const SDL_Event &event);
};

enum Align{AlignLeft, AlignCentre, AlignRight};

// Label is a basic element that contains the common functions for rendering text
class Label : public Element, public sdl::Text
{
public:
    sdl::Colour background;
    Align align;
    Label();
    virtual void render();
    virtual void render(Rect tpos, bool offset = false);
};

class Button : public Label
{
protected:
    bool mHasMouse, mHover;
public:
    sdl::Colour background, hoverBackground;
    bool drawFrame, threeDimensionalEffect;

    Button();
    Button(Rect cpos, std::string ctext, Container* parent = NULL);
    virtual void render();
    virtual void event(const SDL_Event &event);
};

class SBar : public Element
{
protected:
    unsigned long int mDragValue, mDragStartY;
    bool mHasMouse;
public:
    unsigned long int max, value, offset, minSize;
    sdl::Colour colour, background;
    bool drawFrame;

    SBar();
    virtual void render();
    virtual void event(const SDL_Event &event);
};

class ListContainer : public Element
{
protected:
    Label *renderer;
    Rect oldpos;

public:
    SBar scrollbar;
    bool aalias;
    Font * font;
    Align align;
    Colour colour, background, activeBackground;
    unsigned int selection, scrollWidth, itemHeight;
    Rect listPos;
    // This is only used by getItem. If you override ListContainer, you may implement your own database.
    std::vector <std::string>* list;

    ListContainer();
    ListContainer(Rect cpos, std::vector <std::string>* clist, Container* parent = NULL);
    virtual std::string getItem(int number);
    virtual unsigned int getSize();
    virtual void recalcSize();
    virtual void render();
    virtual void event(const SDL_Event &event);
};

class Event
{
    SDL_Event mEvent;
    int mouseX, mouseY;
public:
    Event();
    Event(Element* src);
    Event(SDL_Event &cEvent);

    bool valid();
    Element* source();

    void push();

    void saveMouse();
    void pushMouse();
};
}
} // namespace gui & sdl
